home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Programming / MuManual / C_Sources / MuFastRom.c < prev    next >
C/C++ Source or Header  |  1999-11-28  |  21KB  |  546 lines

  1. /*****************************************************************
  2.  ** MuFastRom                                                   **
  3.  **                                                             **
  4.  ** A MMU-Library compatible ROM remapper                       **
  5.  ** Version 40.8 28.11.1999 © THOR-Software, by Thomas Richter  **
  6.  *****************************************************************/
  7.  
  8. /// Includes
  9. #include <exec/types.h>
  10. #include <exec/memory.h>
  11. #include <exec/ports.h>
  12. #include <dos/dos.h>
  13. #include <mmu/mmubase.h>
  14. #include <mmu/context.h>
  15. #include <mmu/mmutags.h>
  16. #include <workbench/startup.h>
  17.  
  18. #include <proto/exec.h>
  19. #include <proto/mmu.h>
  20. #include <proto/dos.h>
  21. #include <proto/icon.h>
  22. #include <string.h>
  23. ///
  24. /// Defines
  25. #define STRINGDATE "28.11.99"
  26. #define STRINGVERSION "40.8"
  27. #define ROMEND 0x01000000L
  28. #define MAGIC_ROMEND 0x14L
  29. #define CACHEFLAGS (MAPP_CACHEINHIBIT|MAPP_COPYBACK|MAPP_NONSERIALIZED|MAPP_IMPRECISE)
  30. #define TEMPLATE "ON=FASTROM/S,OFF=NOFASTROM/S,HEAD/S,PROTECT/S,NOPROTECT/S"
  31.  
  32. #define OPT_ON  0
  33. #define OPT_OFF 1
  34. #define OPT_HEAD 2
  35. #define OPT_PROTECT 3
  36. #define OPT_NOPROTECT 4
  37. #define OPT_WINDOW 5
  38. #define OPT_COUNT 6
  39. ///
  40. /// Statics
  41. struct MMUBase *MMUBase;
  42. struct DosLibrary *DOSBase;
  43. struct ExecBase *SysBase;
  44. struct Library *IconBase;
  45. ///
  46. /// Protos
  47. int __asm __saveds main(void);
  48. int BuildFastRom(LONG head,LONG protect,LONG noprotect);
  49. int RemoveFastRom(void);
  50. BOOL MapToRom(struct MMUContext *ctx,ULONG source,ULONG mem,ULONG size);
  51. BOOL RemapToRam(struct MMUContext *ctx,ULONG source,ULONG pmem,ULONG mem,ULONG size,LONG protect,LONG noprotect,ULONG cacheflags);
  52. struct RDArgs *ReadTTArgs(struct WBStartup *msg,LONG args[],struct RDArgs **tmp);
  53. ///
  54. /// Strukturen
  55. struct FastRomPort {
  56.         struct MsgPort          frp_Port;
  57.         UBYTE                   frp_NoProtect;
  58.         UBYTE                   frp_Protect;
  59.         void                   *frp_Logical;            /* Logical address of the remapped ROM */
  60.         void                   *frp_Physical;           /* Physical location of the RAM used for remapping */
  61.         void                   *frp_RomStart;
  62.         ULONG                   frp_Size;               /* size of the allocated memory */
  63.         struct Library         *frp_Base;               /* Keep the library open */
  64.         ULONG                   frp_CacheFlags;         /* keeps the cache mode of the remapped ROM */
  65.         char                    frp_Name[32];           /* keeps the name of the port */
  66. };
  67. ///
  68.  
  69. char version[]="$VER: MuFastRom " STRINGVERSION " (" STRINGDATE ") © THOR";
  70.  
  71. /// main
  72. int __asm __saveds main(void)
  73. {
  74. LONG args[OPT_COUNT];
  75. struct RDArgs *rd,*myrd;
  76. struct Process *proc;
  77. int rc=20;
  78. LONG err;
  79. struct WBStartup *msg;
  80. BPTR oldout;
  81. struct MsgPort *oldconsole;
  82.  
  83.  
  84.  
  85.         SysBase=*((struct ExecBase **)(4L));
  86.  
  87.         memset(args,0,sizeof(LONG)*OPT_COUNT);
  88.         /* Wait for the workbench startup, if any */
  89.         proc=(struct Process *)FindTask(NULL);
  90.  
  91.         if (!(proc->pr_CLI)) {
  92.                 WaitPort(&(proc->pr_MsgPort));
  93.                 msg=(struct WBStartup *)GetMsg(&(proc->pr_MsgPort));
  94.         } else  msg=NULL;
  95.  
  96.         if (DOSBase=(struct DosLibrary *)OpenLibrary("dos.library",37L)) {
  97.                 if (MMUBase=(struct MMUBase *)OpenLibrary("mmu.library",41L)) {
  98.  
  99.                         err=ERROR_REQUIRED_ARG_MISSING;
  100.  
  101.                         myrd=NULL;      /* reset the temporary ReadArgs */
  102.                         oldout=NULL;
  103.                         oldconsole=NULL;
  104.                         if (msg) {
  105.                                 oldout=SelectOutput(NULL);
  106.                                 oldconsole=SetConsoleTask(NULL);
  107.                                 rd=ReadTTArgs(msg,args,&myrd);
  108.                         } else  rd=ReadArgs(TEMPLATE,args,NULL);
  109.  
  110.                         if (rd) {
  111.                                 if (!GetMMUType()) {
  112.                                         Printf("MuFastRom requires a working MMU.\n");
  113.                                         err=10;
  114.                                 } else {
  115.                                         /* Argument parser worked, call main routine */
  116.                                         if ((args[OPT_ON]) || (!args[OPT_OFF])) /* ON is the default if OFF is not given */
  117.                                                 err=BuildFastRom(args[OPT_HEAD],args[OPT_PROTECT],args[OPT_NOPROTECT]);
  118.  
  119.                                         if (args[OPT_OFF])
  120.                                                 err=RemoveFastRom();
  121.                                 }
  122.  
  123.                                 FreeArgs(rd);
  124.                                 if (myrd) FreeDosObject(DOS_RDARGS,myrd);
  125.                                 if (msg)  Close(SelectOutput(NULL));
  126.                         } else  err=IoErr();
  127.  
  128.                         if (msg) {
  129.                                 SelectOutput(oldout);
  130.                                 SetConsoleTask(oldconsole);
  131.                         }
  132.  
  133.                         if (err<64) {
  134.                                 rc=err;
  135.                                 err=0;
  136.                         } else {
  137.                                 if (!msg) PrintFault(err,"MuFastRom failed");
  138.                                 rc=10;
  139.                         }
  140.                         SetIoErr(err);
  141.  
  142.                         CloseLibrary((struct Library *)MMUBase);
  143.                 } else if (!msg) PrintFault(ERROR_OBJECT_NOT_FOUND,"MuFastRom requires the mmu.library V41 or better");
  144.                 CloseLibrary((struct Library *)DOSBase);
  145.         }
  146.  
  147.         if (msg) {
  148.                 Forbid();
  149.                 ReplyMsg((struct Message *)msg);
  150.         }
  151.  
  152.         return rc;
  153. }
  154. ///
  155. /// ReadTTArgs
  156. struct RDArgs *ReadTTArgs(struct WBStartup *msg,LONG args[],struct RDArgs **tmp)
  157. {
  158. struct WBArg *wbarg;
  159. struct DiskObject *dop;
  160. char **tt;                      /* ToolTypes array */
  161. char *wbstr;                    /* Our self-made workbench argument string */
  162. char *here;
  163. BPTR oldlock;
  164. ULONG len;
  165. struct RDArgs *rd=NULL,*myrd=NULL;
  166. LONG err=0;
  167. BPTR newout;
  168.  
  169.         if (IconBase=OpenLibrary("icon.library",37L)) {
  170.                 if (wbarg=msg->sm_ArgList) {
  171.                         /* use a project icon if there is one... */
  172.                         if (msg->sm_NumArgs > 1) wbarg++;
  173.  
  174.                         /* go into the directory */
  175.                         oldlock=CurrentDir(wbarg->wa_Lock);
  176.  
  177.                         if (dop=GetDiskObject(wbarg->wa_Name)) {
  178.                                 if (tt=dop->do_ToolTypes) {
  179.                                         /* Read a special tool type for the output window */
  180.  
  181.                                         /* Calc the size of the argument string */
  182.  
  183.                                         len = 3;        /* reserve space for SPC,LF,NUL */
  184.                                         while (*tt) {
  185.                                                 len += strlen(*tt)+1;   /* string, plus space */
  186.                                                 tt++;
  187.                                         }
  188.  
  189.                                         if (wbstr=AllocVec(len,MEMF_PUBLIC)) {
  190.                                                 /* Now copy the arguments into this string, one by one
  191.                                                    and check whether the argument string is still valid. */
  192.  
  193.                                                 tt=dop->do_ToolTypes;
  194.                                                 here=wbstr;
  195.                                                 do{
  196.                                                         *here='\0';                     /* terminate string */
  197.                                                         /* Check whether this tool type is
  198.                                                            commented out. Just ignore it in this case */
  199.                                                         if (*tt) {
  200.                                                                 if (**tt=='(' || **tt==';')
  201.                                                                         continue;
  202.  
  203.                                                                 strcpy(here,*tt);      /* Add TT string */
  204.                                                         }
  205.                                                         len=strlen(here);
  206.                                                         here[len]='\n';
  207.                                                         here[len+1]='\0';               /* terminate string */
  208.  
  209.                                                         /* Now try to ReadArg' this string */
  210.  
  211.                                                         /* release old arguments left over from last loop */
  212.                                                         if (rd) FreeArgs(rd);
  213.                                                         if (myrd) FreeDosObject(DOS_RDARGS,myrd);
  214.                                                         rd=NULL;
  215.                                                         memset(args,0,sizeof(LONG)*OPT_COUNT);
  216.  
  217.                                                         if (myrd=AllocDosObject(DOS_RDARGS,NULL)) {
  218.                                                                 /* Allocate and setup the ReadArgs source */
  219.                                                                 myrd->RDA_Source.CS_Buffer=wbstr;
  220.                                                                 myrd->RDA_Source.CS_Length=strlen(wbstr);
  221.  
  222.                                                                 if (rd=ReadArgs(TEMPLATE ",WINDOW/K",args,myrd)) {
  223.                                                                         /* Is this still valid? */
  224.                                                                         here[len]=' ';
  225.                                                                         here+=len+1;
  226.                                                                         /* if so, accept this argument and go on */
  227.                                                                 } else {
  228.                                                                         err=IoErr();
  229.                                                                         if (err==ERROR_NO_FREE_STORE) break;
  230.                                                                         else    err=0;  /* Ignore unknown or invalid arguments silently */
  231.                                                                 }
  232.                                                         } else {
  233.                                                                 err=ERROR_NO_FREE_STORE;
  234.                                                                 break;
  235.                                                         }
  236.                                                 }while(*tt++);
  237.  
  238.                                                 FreeVec(wbstr);
  239.                                         } else err=ERROR_NO_FREE_STORE;
  240.                                 } else err=ERROR_REQUIRED_ARG_MISSING; /* Huh, how should this happen ? */
  241.                                 FreeDiskObject(dop);
  242.                         } else err=IoErr();
  243.                         CurrentDir(oldlock);
  244.                 } else err=ERROR_REQUIRED_ARG_MISSING; /* This should not happen either */
  245.                 CloseLibrary(IconBase);
  246.         } else err=ERROR_OBJECT_NOT_FOUND;    /* This should not happen */
  247.  
  248.         /* Open an output stream */
  249.  
  250.         if (err==0) {
  251.                 if (newout=Open((args[OPT_WINDOW])?((char *)args[OPT_WINDOW]):("NIL:"),MODE_NEWFILE)) {
  252.                         SelectOutput(newout);
  253.                         /* Hack in the output console. Well, well... */
  254.                         SetConsoleTask(((struct FileHandle *)(BADDR(newout)))->fh_Type);
  255.                 } else err=IoErr();
  256.         }
  257.  
  258.         if (err) {
  259.                 if (rd)   FreeArgs(rd);
  260.                 if (myrd) FreeDosObject(DOS_RDARGS,myrd);
  261.                 SetIoErr(err);
  262.                 rd=NULL;
  263.                 myrd=NULL;
  264.         }
  265.  
  266.         *tmp=myrd;
  267.         return rd;
  268. }
  269. ///
  270. /// BuildFastRom
  271. int BuildFastRom(LONG head,LONG protect,LONG noprotect)
  272. {
  273. void *mem,*source,*pmem;
  274. ULONG size,psize;
  275. ULONG props;
  276. struct FastRomPort *port;
  277. struct MMUContext *ctx,*sctx;   /* default context, supervisorcontext */
  278. struct MinList *ctxl,*sctxl;
  279. int err=ERROR_NO_FREE_STORE;
  280.  
  281.  
  282.         Forbid();                               /* Shut up PatchWork */
  283.  
  284.         /* If this is already installed, warn and return. */
  285.  
  286.         if (FindPort("« MuFastRom »")) {
  287.                 Permit();
  288.                 Printf("MuFastRom already running.\n");
  289.                 return 5;
  290.         }
  291.  
  292.         Permit();
  293.  
  294.         ctx=DefaultContext();   /* get the default context */
  295.         sctx=SuperContext(ctx); /* get the supervisor context for this one */
  296.  
  297.         /* Read the size of the ROM */
  298.         size=*((ULONG *)(ROMEND-MAGIC_ROMEND));
  299.  
  300.         /* The start of the ROM */
  301.         source=((UBYTE *)ROMEND)-size;
  302.  
  303.         props=GetProperties(sctx,(ULONG)source,TAG_DONE);
  304.         props|=GetProperties(ctx,(ULONG)source,TAG_DONE);
  305.  
  306.         if (props & MAPP_REMAPPED) {
  307.                 Printf("The ROM is already remapped to RAM.\n");
  308.                 return 5;
  309.         }
  310.  
  311.  
  312.         /* now allocate the memory for the ROM image. To keep the
  313.            MMU tables as effective as possible, we try to align
  314.            this */
  315.  
  316.         /* We request FAST here, explicitly. Taking chip memory for the
  317.            ROM image doesn't make sense, this isn't fast either... */
  318.  
  319.         mem=AllocAligned(size,(head)?(MEMF_PUBLIC|MEMF_FAST):(MEMF_REVERSE|MEMF_PUBLIC|MEMF_FAST),RemapSize(ctx));
  320.         if (mem) {
  321.  
  322.                 pmem=mem;
  323.                 psize=size;
  324.                 PhysicalLocation(ctx,&pmem,&psize);
  325.                 if (psize!=size) {
  326.                         Printf("The destination memory is fragmentated, unsupported.\n");
  327.                 } else {
  328.  
  329.                  /* Read the cache flags */
  330.                  props=GetProperties(ctx,(ULONG)mem,TAG_DONE) & CACHEFLAGS;
  331.  
  332.                  /* Copy the ROM */
  333.                  CopyMemQuick(source,mem,size);
  334.  
  335.                  /* Write it out, really */
  336.                  CacheClearU();
  337.  
  338.                  port=AllocMem(sizeof(struct FastRomPort),MEMF_PUBLIC|MEMF_CLEAR);
  339.                  if (port) {
  340.                         LockContextList();
  341.                         LockMMUContext(ctx);
  342.                         LockMMUContext(sctx);
  343.                         if (ctxl=GetMapping(ctx)) {
  344.                          if (sctxl=GetMapping(ctx)) {
  345.                           if (RemapToRam(ctx,(ULONG)source,(ULONG)pmem,(ULONG)mem,size,protect,noprotect,props)) {
  346.                            if (RemapToRam(sctx,(ULONG)source,(ULONG)pmem,(ULONG)mem,size,protect,noprotect,props)) {
  347.                             if (RebuildTrees(ctx,sctx,NULL)) {
  348.  
  349.                                         /* we're done now */
  350.                                         port->frp_Port.mp_Node.ln_Type=NT_MSGPORT;
  351.                                         port->frp_Port.mp_Node.ln_Name=port->frp_Name;
  352.                                         strcpy(port->frp_Name,"« MuFastRom »");
  353.                                         port->frp_Port.mp_Flags=PA_IGNORE;
  354.                                         NewList(&(port->frp_Port.mp_MsgList));
  355.  
  356.                                         port->frp_RomStart=source;
  357.                                         port->frp_Physical=pmem;
  358.                                         port->frp_Logical=mem;
  359.                                         port->frp_Size=size;
  360.                                         port->frp_NoProtect=noprotect;
  361.                                         port->frp_Protect=protect;
  362.                                         port->frp_CacheFlags=props;
  363.                                         port->frp_Base=OpenLibrary("mmu.library",0L);
  364.                                         AddPort(&(port->frp_Port));
  365.  
  366.                                         /* Do not release the memory or the port */
  367.                                         mem=NULL;
  368.                                         port=NULL;
  369.  
  370.                                         err=0;
  371.                             }
  372.                            }
  373.                           }
  374.  
  375.                           if (err) {
  376.                                   SetPropertyList(ctx,ctxl);
  377.                                   SetPropertyList(sctx,sctxl);
  378.                           }
  379.  
  380.                           ReleaseMapping(sctx,sctxl);
  381.                          }
  382.                          ReleaseMapping(ctx,ctxl);
  383.                         }
  384.  
  385.                         UnlockMMUContext(sctx);
  386.                         UnlockMMUContext(ctx);
  387.                         UnlockContextList();
  388.                         if (port) FreeMem(port,sizeof(struct FastRomPort));
  389.                  }
  390.                 }
  391.                 if (mem) FreeMem(mem,size);
  392.         }
  393.  
  394.         return err;
  395. }
  396. ///
  397. /// RemoveFastRom
  398. int RemoveFastRom(void)
  399. {
  400. struct MMUContext *ctx,*sctx;
  401. struct MinList *ctxl,*sctxl;
  402. struct FastRomPort *port;
  403. ULONG size,props;
  404. void *mem,*pmem,*source;
  405. int err=ERROR_NO_FREE_STORE;
  406.  
  407.  
  408.         Forbid();                               /* Shut up PatchWork */
  409.  
  410.         /* If this is not installed, warn and return. */
  411.  
  412.         port=(struct FastRomPort *)FindPort("« MuFastRom »");
  413.  
  414.         if (port==NULL) {
  415.                 Permit();
  416.                 Printf("MuFastRom not installed.\n");
  417.                 return 5;
  418.         }
  419.         /* Remove it, to ensure nobody else tries to remove it */
  420.         RemPort(&(port->frp_Port));
  421.         Permit();
  422.  
  423.         ctx=DefaultContext();   /* get the default context */
  424.         sctx=SuperContext(ctx); /* get the supervisor context for this one */
  425.  
  426.         size=port->frp_Size;
  427.         pmem=port->frp_Physical;
  428.         mem=port->frp_Logical;
  429.         source=port->frp_RomStart;
  430.         props=port->frp_CacheFlags;
  431.  
  432.         /* Remove the properties right here... */
  433.  
  434.         LockContextList();
  435.         LockMMUContext(ctx);
  436.         LockMMUContext(sctx);
  437.  
  438.         if (ctxl=GetMapping(ctx)) {
  439.          if (sctxl=GetMapping(sctx)) {
  440.           if (MapToRom(ctx,(ULONG)source,(ULONG)mem,size)) {
  441.            if (MapToRom(sctx,(ULONG)source,(ULONG)mem,size)) {
  442.             if (RebuildTrees(ctx,sctx,NULL)) {
  443.  
  444.                         FreeMem(mem,size);
  445.  
  446.                         /* Close the mmu.lib so it can be flushed... */
  447.  
  448.                         if (port->frp_Base)
  449.                                 CloseLibrary(port->frp_Base);
  450.  
  451.                         FreeMem(port,sizeof(struct FastRomPort));
  452.                         err=0;
  453.             }
  454.            }
  455.           }
  456.  
  457.           if (err) {
  458.                   SetPropertyList(ctx,ctxl);
  459.                   SetPropertyList(sctx,sctxl);
  460.           }
  461.  
  462.           ReleaseMapping(sctx,sctxl);
  463.          }
  464.          ReleaseMapping(ctx,ctxl);
  465.         }
  466.  
  467.         UnlockMMUContext(sctx);
  468.         UnlockMMUContext(ctx);
  469.         UnlockContextList();
  470.  
  471.         if (err) {
  472.                 /* Better luck next time... */
  473.                 AddPort(&(port->frp_Port));
  474.                 Printf("Can't remove the FastRom node, sorry.\n");
  475.         }
  476.  
  477.         return err;
  478. }
  479. ///
  480. /// RemapToRam
  481. BOOL RemapToRam(struct MMUContext *ctx,ULONG source,ULONG pmem,ULONG mem,ULONG size,LONG protect,LONG noprotect,ULONG cacheflags)
  482. {
  483. ULONG oldprops;
  484. ULONG rommask,mirrormask;
  485.  
  486.         /* get the properties of the ROM */
  487.         oldprops=GetProperties(ctx,source,TAG_DONE);
  488.  
  489.         oldprops |= MAPP_REMAPPED;
  490.         rommask=MAPP_REMAPPED|MAPP_COPYBACK;   /* Define these bits for the ROM image */
  491.         mirrormask=0;                          /* ...and these for the RAM mirror */
  492.  
  493.         /* Protection enabled? */
  494.         if (protect) {
  495.                 /* active or passive protection? */
  496.                 if (oldprops & MAPP_WRITEPROTECTED) {
  497.                         /* here aggressive, enable protection
  498.                            and allow MuForce to repair access faults */
  499.                         rommask |= MAPP_WRITEPROTECTED|MAPP_REPAIRABLE;
  500.                         mirrormask |= MAPP_WRITEPROTECTED|MAPP_REPAIRABLE;
  501.                 } else {
  502.                         rommask |= MAPP_ROM;
  503.                         mirrormask |= MAPP_ROM;
  504.                         oldprops |= MAPP_ROM;
  505.                 }
  506.         } else if (noprotect) {
  507.                 /* disable all kinds of protection */
  508.                 oldprops &= ~(MAPP_ROM|MAPP_WRITEPROTECTED);
  509.                 rommask |= MAPP_ROM | MAPP_WRITEPROTECTED;
  510.                 mirrormask |= MAPP_ROM | MAPP_WRITEPROTECTED;
  511.         }
  512.  
  513.         /* Enter caching mode */
  514.         oldprops &= ~CACHEFLAGS;
  515.         oldprops |= cacheflags;
  516.         rommask |= CACHEFLAGS;
  517.  
  518.         if (SetProperties(ctx,oldprops,rommask,source,size,MAPTAG_DESTINATION,pmem,TAG_DONE)) {
  519.          if (SetProperties(ctx,oldprops,mirrormask,mem,size,TAG_DONE)) {
  520.            return TRUE;
  521.          }
  522.         }
  523.  
  524.         return FALSE;
  525. }
  526. ///
  527. /// MapToRom
  528. BOOL MapToRom(struct MMUContext *ctx,ULONG source,ULONG mem,ULONG size)
  529. {
  530.  
  531.         if (SetProperties(ctx,0,MAPP_REMAPPED|CACHEFLAGS,source,size,TAG_DONE)) {
  532.          if (SetProperties(ctx,0,MAPP_ROM|MAPP_WRITEPROTECTED|MAPP_REPAIRABLE,mem,size,TAG_DONE)) {
  533.            return TRUE;
  534.          }
  535.         }
  536.  
  537.         return FALSE;
  538. }
  539. ///
  540.  
  541.  
  542.  
  543.  
  544.  
  545.  
  546.